package com.boarsoft.boar.sys;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.boarsoft.common.Util;

import sun.misc.BASE64Encoder;

@SuppressWarnings("restriction")
public class Mailer {
	protected Log log = LogFactory.getLog(this.getClass());
	protected String fromAddr = null; // 账号
	protected String fromName = null; // 用户名
	protected String password = null; // 密码
	private Properties props;
	/** **/
	private String charset = StandardCharsets.UTF_8.name();

	/**
	 * 发送简单邮件
	 * 
	 * @param toAddr
	 *            收件人邮件地址
	 * @param toName
	 *            收件人显示名称
	 * @param subject
	 *            邮件标题
	 * @param content
	 *            邮件正文
	 * @return
	 */
	public boolean sendSimpleMail(String toAddr, String toName, String subject, String content) {
		Map<String, String> toMap = new HashMap<String, String>();
		toMap.put(toAddr, toName);
		try {
			// List<String> lt = new ArrayList<String>();
			// lt.add("d:/temp/关于发票号管理的解决方案.docx");
			send(toMap, null, null, subject, content, null);
			return true;
		} catch (Exception e) {
			log.error("Error on send simple mail.", e);
		}
		return false;
	}

	/**
	 * 发送邮件，支持附件、抄送、密送
	 * 
	 * @param toMap
	 *            收件人列表，KEY为收件人地址，VALUE为收件人显示名
	 * @param ccMap
	 *            抄送列表
	 * @param bccMap
	 *            密送列表
	 * @param subject
	 *            标题
	 * @param content
	 *            正文
	 * @param attachs
	 *            附件的文件名（带绝对路径）
	 * @throws UnsupportedEncodingException
	 * @throws MessagingException
	 */
	public void send(Map<String, String> toMap, Map<String, String> ccMap, Map<String, String> bccMap, String subject,
			String content, List<String> attachs) throws UnsupportedEncodingException, MessagingException {
		// 检查收件人参数
		if (toMap == null || toMap.size() < 1) {
			throw new IllegalArgumentException();
		}
		// 用配置的props构建一个session
		Session session = Session.getDefaultInstance(props);
		// session.setDebug(true);
		// 用session为参数定义消息对象
		MimeMessage mm = new MimeMessage(session);
		// 设置发件人地址
		InternetAddress from = null;
		if (Util.strIsEmpty(fromName)) {
			from = new InternetAddress(fromAddr);
		} else {
			from = new InternetAddress(fromAddr, fromName);
		}
		mm.setFrom(from);
		// 设置收件人地址
		InternetAddress[] toArr = this.mapToArr(toMap);
		if (toArr != null)
			mm.setRecipients(Message.RecipientType.TO, toArr);
		// 设置抄送地址
		InternetAddress[] ccArr = this.mapToArr(ccMap);
		if (ccArr != null)
			mm.setRecipients(Message.RecipientType.CC, ccArr);
		// 设置密送地址
		InternetAddress[] bccArr = this.mapToArr(bccMap);
		if (bccArr != null)
			mm.setRecipients(Message.RecipientType.BCC, bccArr);
		// 设置标题
		mm.setSubject(subject);
		// 设置邮件正文
		Multipart mp = new MimeMultipart();
		BodyPart mbp = new MimeBodyPart();// 设置邮件的文本内容
		mbp.setContent(content, "text/html;charset=UTF-8");
		// contentPart.setText(content);
		mp.addBodyPart(mbp);
		// 添加附件
		if (attachs != null && attachs.size() > 0) {
			BASE64Encoder enc = new BASE64Encoder();
			for (String fn : attachs) {
				BodyPart bp = new MimeBodyPart();
				// 添加附件的内容
				File f = new File(fn);
				bp.setDataHandler(new DataHandler(new FileDataSource(f)));
				// 添加附件的标题
				bp.setFileName(String.format("=?UTF-8?B?%s?=",//
						enc.encode(f.getName().getBytes(charset))));
				mp.addBodyPart(bp);
			}
		}
		mm.setContent(mp);// 将mulpart对象放到msg中
		mm.saveChanges();// 保存邮件
		// 根据协议类型发送邮件
		Transport tran = session.getTransport("smtp");
		tran.connect(fromAddr, password);// 连接服务器的邮箱
		tran.sendMessage(mm, mm.getAllRecipients());
		tran.close();
	}

	private InternetAddress[] mapToArr(Map<String, String> map) throws UnsupportedEncodingException {
		if (map == null || map.size() < 1)
			return null;
		InternetAddress[] arr = new InternetAddress[map.size()];
		int i = 0;
		for (Entry<String, String> en : map.entrySet()) {
			arr[i] = new InternetAddress(en.getKey(), en.getValue());
			i++;
		}
		return arr;
	}

	public Properties getProps() {
		return props;
	}

	public void setProps(Properties props) {
		this.props = props;
	}

	public String getFromAddr() {
		return fromAddr;
	}

	public void setFromAddr(String fromAddr) {
		this.fromAddr = fromAddr;
	}

	public String getFromName() {
		return fromName;
	}

	public void setFromName(String fromName) {
		this.fromName = fromName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getCharset() {
		return charset;
	}

	public void setCharset(String charset) {
		this.charset = charset;
	}

}
